package com.hzb.LNReader.view;

import java.io.File;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import com.hzb.LNReader.ImageViewerActivity;
import com.hzb.LNReader.ReaderActivity;
import com.hzb.LNReader.ReaderContext;

public class ReaderView extends ScrollView {

	public static final char IMG_CODE = '!';
	
	private LinearLayout widgetList;
	private LinearLayout tmpList;
	
	private int lineHeight;
	public static int screenWidth;
	public static int screenHeight;
	private int pendingHeight;
	
	public int currHeight;
	public int seqFrom = 0;
	public int seqTo = 0;
	ReaderActivity reader;
	private int fileSize;
	private String parentDir;
//	private TextView process;
	private int fillBottomLimit = Integer.MAX_VALUE;
	
	public ReaderView(ReaderActivity context) {
		super(context);
//		this.process = process;
		this.reader = context;
		File currFile = context.currReadFile.file;
		this.fileSize = (int) currFile.length();
		this.parentDir = currFile.getParent().toString() + '/';
		widgetList = new LinearLayout(this.getContext());
		widgetList.setOrientation(LinearLayout.VERTICAL);
		this.addView(widgetList);
		WindowManager manage = context.getWindowManager();
		Display display = manage.getDefaultDisplay();
		screenWidth = display.getWidth();
		screenHeight = display.getHeight();
		loadingText = new TextView(context);
		loadingText.setText("Loading...");
		loadingText.setTextColor(ReaderContext.fontColor);
		loadingText.setTextSize(ReaderContext.fontSize);
		lineHeight = loadingText.getLineHeight() * 12 / 10;
		setHorizontalScrollBarEnabled(false);
		setVerticalScrollBarEnabled(true);
		setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY);
		
	}
	
	public void reset(int fromSeq) {
		this.seqFrom = this.seqTo = fromSeq;
		widgetList.removeAllViews();
		currHeight = 0;
	}
	
	private boolean isAppend;
	private int firstOffset;
	private int lastOffset;
	
	public int appendViewsBefore(String[] content, int[] fileOffset, int from, int limit) {
		pendingHeight = 0;
		isAppend = false;
		tmpList = new LinearLayout(this.getContext());
		tmpList.setOrientation(LinearLayout.VERTICAL);
		int to = from - limit + 1;
		if (to < 0) to = 0;
		lastOffset = fileOffset[from] + content[from].length();
		int i;
		for (i=from; i >= to; i--) {
			View newView = newViewItem(content[i], fileOffset[i]);
			int tmp = pendingHeight + newView.getMeasuredHeight();
			if (tmp >= ReaderContext.viewBufferHeight) {
				break;
			}
			tmpList.addView(newView, 0);
			pendingHeight += newView.getMeasuredHeight();
		}
		firstOffset = fileOffset[i + 1];
		tmpList.setTag(firstOffset);
		return tmpList.getChildCount();
	}
	
	public int appendViewsAfter(String[] content, int[] fileOffset, int from, int limit) {
		pendingHeight = 0;
		isAppend = true;
		tmpList = new LinearLayout(this.getContext());
		tmpList.setOrientation(LinearLayout.VERTICAL);
		int to = from + limit;
		firstOffset = fileOffset[from];
		tmpList.setTag(firstOffset);
		for (int i=from; i<to; i++) {
			View newView = newViewItem(content[i], fileOffset[i]);
			tmpList.addView(newView);
			pendingHeight += newView.getMeasuredHeight();
		}
		lastOffset = fileOffset[to - 1] + content[to - 1].length();
		return tmpList.getChildCount();
	}
	
	private View newViewItem(String rawStr, int fileOffset) {
		if (rawStr.length() > 2 && rawStr.charAt(0) == IMG_CODE && rawStr.charAt(1) != IMG_CODE) {
			if (rawStr.charAt(2) != '/') {
				return newImage(rawStr.substring(1), fileOffset);
			} else {
				return newImage(rawStr.substring(2), fileOffset);
			}
		} else {
			return newText(rawStr, fileOffset);
		}
	}
	private View newText(String txt, int fileOffset) {
		TextView txtView = new TextView(this.getContext());
		txtView.setTextSize(ReaderContext.fontSize);
		txtView.setTextColor(ReaderContext.fontColor);
		txtView.setText(txt);
		
		txtView.measure(MeasureSpec.makeMeasureSpec(screenWidth,
				MeasureSpec.AT_MOST), MeasureSpec.UNSPECIFIED);
		txtView.setTag(fileOffset);
		return txtView;
	}

	private View newImage(String path, int fileOffset) {
		final String imgPath = parentDir + path;
		File imgFile = new File(imgPath);
		if (!imgFile.isFile()) {
			return newText("文件不存在:" + path, fileOffset);
		}
		Bitmap bmp = BitmapFactory.decodeFile(imgPath);
		if (bmp == null) {
			return newText("无法载入:" + path, fileOffset);
		}
		if (bmp.getWidth() > screenWidth) {
			int scaledHeight = bmp.getHeight() * screenWidth / bmp.getWidth();
			bmp = Bitmap.createScaledBitmap(bmp, screenWidth, scaledHeight, true);
		}
		ImageView imgView = new ImageView(this.getContext());
		imgView.setImageBitmap(bmp);
		imgView.measure(MeasureSpec.makeMeasureSpec(screenWidth,MeasureSpec.AT_MOST), 
				MeasureSpec.UNSPECIFIED);
		imgView.setTag(fileOffset);
		imgView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent intent = new Intent(reader, ImageViewerActivity.class);
				intent.putExtra(ImageViewerActivity.DST_IMG, imgPath);
				reader.startActivity(intent);
			}
		});
		return imgView;
	}
	boolean needRemove = false;
	TextView loadingText;
	public void addPendingHeight() {
		widgetList.setMinimumHeight(currHeight + pendingHeight);
		widgetList.addView(loadingText);
		needRemove = true;
	}
	int topProcess, totalProcess;
	public void flushAppender() {
		widgetList.setMinimumHeight(0);
		if (needRemove) {
			widgetList.removeViewAt(widgetList.getChildCount() - 1);
			needRemove = false;
		}
//		int scrollY;
		if (isAppend) {
			flushAppenderAfter();
		} else {
			flushAppenderBefore();
		}
		if (fileSize != 0) {
			topProcess = firstOffset * 1000 / fileSize;
			totalProcess = (lastOffset - firstOffset) * 1000 / fileSize;
		}
//		updateProcess(scrollY);
		fillBottomLimit = currHeight - (screenHeight << 1);
	}
	
	public int flushAppenderAfter() {
		int scrollY = getScrollY();
//		currHeight = widgetList.getHeight();
		
		int lowestTop = currHeight - ReaderContext.viewBufferHeight - screenHeight;
		if (lowestTop > scrollY) lowestTop = scrollY;
		lowestTop -= 100;
		int removeHeight = 0;
		for (;;) {
			LinearLayout tmp = (LinearLayout) widgetList.getChildAt(0);
			if (tmp == null) break;
			if (tmp.getBottom() >= lowestTop) {
				firstOffset = (Integer)tmp.getTag();
				removeHeight = tmp.getTop();
				break; 
			}
			widgetList.removeViewAt(0);
			seqFrom += tmp.getChildCount();
			firstOffset = (Integer) tmp.getTag();
		}
		widgetList.addView(tmpList);
		seqTo += tmpList.getChildCount();
		scrollY -= removeHeight;
		this.scrollTo(0, scrollY);
		currHeight = currHeight - removeHeight + pendingHeight;
		return scrollY;
	}
	public int flushAppenderBefore() {
		int scrollY = getScrollY();
//		currHeight = widgetList.getHeight();
		
		int removeIndex = widgetList.getChildCount() - 1;
		int highestBottom = ReaderContext.viewBufferHeight;
		if (highestBottom < scrollY + screenHeight) highestBottom = scrollY + screenHeight;
		highestBottom += 100;
		
		for (;;) {
			LinearLayout tmp = (LinearLayout)widgetList.getChildAt(removeIndex);
			if (tmp == null) break;
			if (tmp.getTop() < highestBottom) {
				lastOffset = (Integer) tmp.getTag();
				currHeight = tmp.getBottom() + pendingHeight;
				break;
			}
			widgetList.removeViewAt(removeIndex--);
			seqTo -= tmp.getChildCount();
		}
		widgetList.addView(tmpList, 0);
		seqFrom -= tmpList.getChildCount();
		scrollY += pendingHeight;
		scrollTo(0, scrollY);
		return scrollY;
	}

	public void scrollNextPage() {
		smoothScrollBy(0, this.getHeight() - lineHeight);
	}

	public void scrollPrevPage() {
		smoothScrollBy(0, lineHeight - this.getHeight());
	}


	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
//		int diff = oldt - t;
//		if (diff < 10 && -10 < diff) {
//			updateProcess(t);
//		}
		
		if (t >= fillBottomLimit && t > oldt) {
			if (reader.fillTask == null && reader.currReadFile.maxLineSeq > seqTo) {
				reader.fillConent(true);
			}
		}
		
		if (t < screenHeight && t < oldt) {
			if (reader.fillTask == null && seqFrom > 0) {
				reader.fillConent(false);
			}
			
		}
		super.onScrollChanged(l, t, oldl, oldt);
	}

//	public void updateProcess(int t) {
//		if (currHeight != 0) {
//			int p = topProcess + t * totalProcess / currHeight;
//			process.setText(Integer.toString(p));
//		}
//	}

	public int getTextHeight() {
		return widgetList.getHeight();
	}
	
	/**
	 * 获取当前的显示位置信息
	 * @return 	int[2],其中[0]表示显示范围内第一个控件的所在行号，
	 * 			[1]表示显示的便宜量.
	 * 			[2]表示当前进度
	 */
	public int[] getPosition() {
		int oCount = widgetList.getChildCount();
		int scrollY = getScrollY();
		int[] ret = new int[] {seqFrom, 0, 0};
		if (currHeight != 0) {
			ret[2] = topProcess + getScrollY() * totalProcess / currHeight;
		}
		
		for (int i=0; i<oCount; i++) {
			LinearLayout txtBatch = (LinearLayout) widgetList.getChildAt(i);
			if (txtBatch.getBottom() > scrollY) {
				int iCount = txtBatch.getChildCount();
				int lastBatchTop = txtBatch.getTop();
				int innerScrollY = scrollY - lastBatchTop;
				for (int j=0; j<iCount; j++) {
					View lastView = txtBatch.getChildAt(j);
					if (lastView.getBottom() > innerScrollY) {
						ret[1] = innerScrollY - lastView.getTop();
						return ret;
					}
					ret[0]++;
				}
				break;
			} else {
				ret[0] += txtBatch.getChildCount();
			}
		}
		ret[0] --;
		return ret;
	}
	
}
